﻿/// File: ViewletControls\picturebox.fs
/// 
/// Author: Giacomo Righetti (righetti@di.unipi.it)
///   
/// ------------------------------------------------------------
/// Copyright (c) Microsoft Corporation.  All rights reserved.
/// 
/// The use and distribution terms for this software are 
/// contained in the file named license.txt, which can be found 
/// in the root of this distribution.
/// By using this software in any fashion, you are agreeing to 
/// be bound by the terms of this license.
///
/// You must not remove this notice, or any other, from this
/// software.
/// ------------------------------------------------------------

namespace LightweightControls

open System.Drawing
open System.Windows.Forms

///
/// Summary:
///     The lightweight version of the picture box control.
type LightweightPictureBox() as x =
    inherit LightweightControl()
    
    let mutable borderStyle = BorderStyle.None
    let mutable sizeMode = PictureBoxSizeMode.Normal
    
    let mutable image : Image = null
    let mutable errorImage : Image = null
    
    ///
    /// Summary:
    ///     Indicates the border style for the control.
    ///
    /// Returns:
    ///     One of the System.Windows.Forms.BorderStyle enumeration values. 
    ///     The default is System.Windows.Forms.BorderStyle.None.
    member x.BorderStyle
        with get() = borderStyle
        and set(value) =
            if borderStyle <> value then 
                borderStyle <- value
                if sizeMode = PictureBoxSizeMode.AutoSize then
                    x.fitToImage()
                base.Invalidate()
    
    ///
    /// Summary:
    ///     Gets or sets the image that is displayed on a button control.
    ///
    /// Returns:
    ///     The System.Drawing.Image displayed on the button control. 
    ///     The default value is null.   
    member x.Image
        with get() = image
        and set(value) = 
            if image <> value then
                image <- value
                if value <> null && sizeMode = PictureBoxSizeMode.AutoSize then
                    x.fitToImage()
                base.Invalidate()
    
    ///
    /// Summary:
    ///     Gets or sets the image to display when an error occurs during the image-loading
    ///     process or if the image load is canceled.
    ///
    /// Returns:
    ///     An System.Drawing.Image to display if an error occurs during the image-loading
    ///     process or if the image load is canceled.
    member x.ErrorImage
        with get() = errorImage
        and set(value) =
            if errorImage <> value then
                errorImage <- value
                base.Invalidate() 

    ///
    /// Summary:
    ///     Indicates how the image is displayed.
    ///
    /// Returns:
    ///     One of the System.Windows.Forms.PictureBoxSizeMode values. The default is
    ///     System.Windows.Forms.PictureBoxSizeMode.Normal.
    member x.SizeMode
        with get() = sizeMode
        and set(value) =
            if sizeMode <> value then
                sizeMode <- value
                if sizeMode = PictureBoxSizeMode.AutoSize then
                    x.fitToImage()
                base.Invalidate()
    
    member private x.fitToImage() =
        x.Width <- image.Width
        x.Height <- image.Height
        if borderStyle = BorderStyle.FixedSingle then
            x.Width <- image.Width + 2
            x.Height <- image.Height + 2
        elif borderStyle = BorderStyle.Fixed3D then
            x.Width <- image.Width + 4
            x.Height <- image.Height + 4           
            
    override x.OnPaint (e) = 
        if image <> null then
            let g = e.Graphics
            
            // translatation of the image relative to the upper left corner of the border.
            let mutable offset = 0
            
            // draws the border
            if borderStyle = BorderStyle.FixedSingle then
                ControlPaint.DrawBorder(g, x.ClientRectangle, SystemColors.ControlDarkDark, ButtonBorderStyle.Solid)
                offset <- 1
            elif borderStyle = BorderStyle.Fixed3D then
                ControlPaint.DrawBorder3D(g, x.ClientRectangle, Border3DStyle.Sunken, Border3DSide.All)
                offset <- 2
                
            // draws the image
            match sizeMode with
            | PictureBoxSizeMode.AutoSize 
            | PictureBoxSizeMode.Normal -> g.DrawImage(image, offset, offset)
            | PictureBoxSizeMode.CenterImage -> 
                let cx = (x.Width - image.Width) / 2
                let cy = (x.Height - image.Height) / 2
                g.DrawImage(image, cx, cy)
            | PictureBoxSizeMode.StretchImage -> g.DrawImage(image, offset, offset, x.Width - 2*offset, x.Height - 2*offset)
            | PictureBoxSizeMode.Zoom -> 
                let size = image.Size
                let num = min (float32 x.ClientRectangle.Width / float32 size.Width) (float32 x.ClientRectangle.Height / float32 size.Height)
                let w = float32 size.Width * num
                let h = float32 size.Height * num
                let rect = RectangleF(float32 offset + (float32 x.ClientRectangle.Width - w) / 2.0f, 
                                      float32 offset + (float32 x.ClientRectangle.Height - h) / 2.0f, 
                                      w - 2.0f * float32 offset, 
                                      h - 2.0f * float32 offset)
                g.DrawImage(image, rect)
            | _ -> failwith "case not supported"